#ifndef _MY_UTIL__
#define _MY_UTIL__
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <time.h>
#include <experimental/filesystem>
#include <sys/stat.h>
#include <jsoncpp/json/json.h>
#include "bundle.h"
namespace fs = std::experimental::filesystem;
namespace cloud{
  class FileUtil{
    private:
      std::string _name;
    public:
      FileUtil(const std::string &name):_name(name)
    {}
      std::string Name()
      {
        return fs::path(_name).filename().string();//返回去除路径后的纯文件名
      }




      bool Exists()
      {
        return fs::exists(_name);
      }//文件是否存在

     


      
      size_t Size()
      {
        if(this->Exists()==false)
        {
          return 0;
        }
        return fs::file_size(_name);
      }//文件大小






      time_t MTime()
      {
        if(this->Exists()==false)
        {
          return 0;
        }
        auto ftime = fs::last_write_time(_name);
        std::time_t cftime = decltype(ftime)::clock::to_time_t(ftime);
        return cftime;
      }//最后一次修改时间






      time_t ATime()
      {
        struct stat st;
        stat(_name.c_str(),&st);
        return st.st_atime;
      }//最后一次访问时间






      bool Remove()                                                                                                                               
      {    
        if (this->Exists() ==false)    
        {                 
          return true;    
        }                 
        fs::remove_all(_name);                                                                          
        return true;                              
      }   






      bool Read(std::string *body){
        if(this->Exists()==false){
          return false;
        }
        std::ifstream ifs;    
        ifs.open(_name, std::ios::binary);    
        if(ifs.is_open() == false){    
          std::cout<<"Read open failed!\n";    
          return false;    
        }     
        size_t fsize =this->Size();

        body->resize(fsize);    
        ifs.read(&(*body)[0], fsize);    
        if(ifs.good() ==false){    
          std::cout<<"read file failed!\n";    
          ifs.close();    
          return false;    
        }    
        ifs.close();    
        return true;       
      }//读取文件所有数据到body中








      bool Write(const std::string &body){              
        std::ofstream ofs;
        ofs.open(_name,std::ios::binary);
        if (ofs.is_open() == false){
          std::cout<<"Write open failed!\n";
          return false;
        }
        ofs.write(body.c_str(), body.size());
        if(ofs.good() == false){
          std::cout<<"write file failed!\n";
          ofs.close();
          return false;
        }
        ofs.close();
        return true;
      }//写入文件








      bool CreateDirectory(){
        if(this->Exists()){
          return true;
        }
        fs::create_directories(_name);
        return true;
      }//创建目录







      //目录迭代器当前默认只能遍历深度为一层的目录
      bool ScanDirectory(std::vector<std::string> *arry){
        if(this->Exists()==false){
          return false;
        }
        for(auto &a : fs::directory_iterator(_name)){
          if(fs::is_directory(a)==true ){//只需要文件，不需要文件夹
            continue; //遍历下一个
          }
          //std::string pathname = fs::path(a).filename().string();
          std::string pathname = fs::path(a).relative_path().string();
          arry->push_back(pathname);
        }
        return true;
      }







      bool Compress(const std::string &packname){
        if(this->Exists()==false){
          return false;
        }
        std::string body;
        if (this->Read(&body)== false)
        {
          std::cout<<"compress read file failed!\n";
          return false;
        }
        std::string packed = bundle::pack(bundle::LZIP,body);
        if(FileUtil(packname).Write(packed) == false)
        {
          std::cout<<"compress write packdata failed!\n";
          return false;
        }
        fs::remove_all(_name);//压缩后删除源文件
        return true;
      }







      bool Uncompress(const std::string &filename){
        if(this->Exists()==false){
          return false;
        }
        std::string body;
        if(this->Read(&body) == false){
          std::cout << "uncompress read file failed!\n";
        }
        std::string unpack_data = bundle::unpack(body);
        if (FileUtil(filename).Write(unpack_data) == false){
          std::cout<<"uncompress write unpack_data failed!\n";
          return false;
        }
        fs::remove_all(_name);//解压后删除压缩包
        return true;
      }


  };

















  class JsonUtil{
    public:
      static bool Serialize(const Json::Value &val,std::string *body){
        Json::StreamWriterBuilder swb;                                                                                                                           
        Json::StreamWriter *sw = swb.newStreamWriter();//new一个StreamWriter对象    
        std::stringstream ss;    
        int ret = sw->write(val,&ss);//实现序列化    
        if(ret!= 0){    
          std::cout<<"serailize failed!\n";    
          delete sw;    
          return false;    
        }    
        *body = ss.str();
        delete sw;
        return true;
      }




      //不需要实例化对象，所以不用this指针，设置成静态可以直接调用
      static bool UnSerialize(const std::string &body,Json::Value *val){
        Json::CharReaderBuilder crb;    
        Json::CharReader *cr = crb.newCharReader();        
        std::string err;    
        bool ret = cr->parse(body.c_str(),body.c_str()+body.size(),val,&err);    
        if(ret == false){    
          std::cout<<"unserialize failed:"<<err<<std::endl;    
          delete cr;    
          return false;     
        }
        delete cr;
        return true;
      }//反序列化

  };
}
#endif
